use std::io::Cursor;
use bytes::{Buf, BufMut, BytesMut};
use log::info;
use tokio::io::{BufWriter};
use tokio::net::TcpStream;

pub struct RpcSocketChannel {
    stream: BufWriter<TcpStream>,
    buffer: BytesMut,
}

pub struct Frame {
    len: usize,
    bytes: BytesMut,
}

impl RpcSocketChannel {
    pub fn new(stream: TcpStream, capacity: usize) -> RpcSocketChannel {
        RpcSocketChannel {
            stream: BufWriter::new(stream),
            buffer: BytesMut::with_capacity(capacity),
        }
    }
}

// impl RpcChannel for RpcSocketChannel {
//     fn write(&mut self, data: Box<dyn RpcEncode>) -> RpcResult<()> {
//         let mut bytes_mut = BytesMut::with_capacity(1024);
//         data.encode(&mut bytes_mut)?;
//         self.stream.write_all(&bytes_mut).await?;
//         self.stream.flush().await?;
//         Ok(())
//     }
// }

impl RpcSocketChannel {

    fn parse(&mut self)-> Option<Frame> {
        let mut buf = Cursor::new(&self.buffer[..]);
        if buf.remaining() < 4 {
            return None;
        }
        let len = buf.get_u32_le() as usize;
        if buf.remaining() < len {
            return None;
        }
        self.buffer.advance(len);
        Some(Frame {
            len,
            bytes: self.buffer.split(),
        })
    }
}

fn parse(bytes_mut: &mut BytesMut)-> Option<Frame> {
    let mut buf = Cursor::new(&bytes_mut[..]);
    if buf.remaining() < 4 {
        return None;
    }
    let len = buf.get_u32_le() as usize;
    if buf.remaining() < len {
        return None;
    }

    Some(Frame {
        len,
        bytes: bytes_mut.split_to(len+4),
    })
}

#[test]
fn parse_test() {
    let mut bytes_mut = BytesMut::with_capacity(1024);
    let str = "asfasfasfasfsafasfasfdas";
    let bytes = str.as_bytes();
    bytes_mut.put_u32_le(bytes.len() as u32);
    bytes_mut.put_slice(bytes);
    let result = parse(&mut bytes_mut);
    match result {
        None => {}
        Some(data) => {
            info!("len: {}, data: {}", data.len, String::from_utf8_lossy(&data.bytes[..]))
        }
    };
    info!("length: {:?}", bytes_mut.len());

}